﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description: DeployPageViewModelBase
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Net;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Threading;

namespace VmroleAuthor.ViewModels
{
    public enum ResExtAzureDeploymentStatus
    {
        InProgress,
        CompletedWithSuccess,
        Failed,
        CompletedWithWarning
    }

    public enum ResExtDeploymentResultMessageCategory
    {
        Success,
        Warning,
        Error,
        Pending
    }

    public class ResExtDeploymentResult
    {
        public HandlerStatusStates Category { get; set; }

        public string Message { get; set; }
    }

    public class ResExtAzureDeploymentData
    {
        internal readonly string FrontEnd;

        internal string SubscriptionId;

        internal string MgtCertThumbprint;

        internal X509Certificate2 MgmtCertificate;

        internal CloudService SelectedCloudService;

        internal VirtualMachine SelectedVirtualMachine;

        internal StorageAccount SelectedStorageAccount;

        internal StorageContainer SelectedStorageContainer;

        internal List<string> ResourceReferencePaths;

        internal bool AreResourcesUploaded;

        internal bool DeleteResourcesAfterDeployment;

        internal bool HasPayload;

        // value keeps track of when the Vm was last successfully updated
        internal DateTime? LastUpdatedTimestamp = null;

        public Dictionary<string, string> ApplicationParameterSettingValues { get; set; }

        /// <summary>
        /// This is the onprem version of resource extension json file
        /// </summary>
        public string ResourceExtensionJson { get; set; }

        /// <summary>
        /// This is the translated Azure resource extension json file
        /// </summary>
        public string AzureResExtProtectedSettings { get; set; }

        /// <summary>
        /// This is the Base64 version of the above AzureResExtProtectedSettings.
        /// This goes in seqno.settings file, under runtime settings
        /// </summary>
        public string AzureResExtBase64EncodedProtectedSettings { get; set; }

        public ResExtAzureDeploymentStatus ResExtAzureDeploymentStatus { get; set; }

        public ResExtDeploymentResult SummaryResultMessage { get; set; }

        public ObservableCollection<ResExtDeploymentResult> AdditionalResultMessages { get; set; }

        public string ErrorCode { get; set; }

        /// <summary>
        /// Eventing mechanism for the ResultsPageViewModel to subscribe to so that it can know that deployment completed
        /// </summary>
        public event EventHandler DeploymentUpdated;

        public void OnDeploymentUpdated()
        {
            EventHandler handler = DeploymentUpdated;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        public ResExtAzureDeploymentData()
        {
            this.FrontEnd = "management.core.windows.net";

            try
            {
                // check if appsettings has values to use
                NameValueCollection appSettings = ConfigurationManager.AppSettings;
                if (appSettings.Count > 0)
                {
                    // frontend point to use
                    var frontEnd = appSettings.GetValues(AzureHelper.FrontEndpoint);
                    if (frontEnd != null && !string.IsNullOrEmpty(frontEnd[0]))
                    {
                        this.FrontEnd = frontEnd[0];
                    }

                    // subscription id
                    var subscriptionId = appSettings.GetValues(AzureHelper.SubscriptionId);
                    if (subscriptionId != null && !string.IsNullOrEmpty(subscriptionId[0]))
                    {
                        this.SubscriptionId = subscriptionId[0];
                    }

                    // cert thumbprint
                    var certThumbprint = appSettings.GetValues(AzureHelper.MgtCertThumbprint);
                    if (certThumbprint != null && !string.IsNullOrEmpty(certThumbprint[0]))
                    {
                        this.MgtCertThumbprint = certThumbprint[0].Trim();
                        this.MgmtCertificate = AzureHelper.GetCertificate(this.MgtCertThumbprint);
                    }

                    // server certificate validation
                    var serverCertValidation = appSettings.GetValues(AzureHelper.ValidateServerCertificate);
                    if (serverCertValidation != null && !string.IsNullOrEmpty(serverCertValidation[0]))
                    {
                        bool validateCert;
                        if (Boolean.TryParse(serverCertValidation[0], out validateCert) && !validateCert)
                        {
                            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                        }
                    }
                }
            }
            catch (ConfigurationErrorsException)
            {
                // log 
            }

            this.ResourceReferencePaths = new List<string>();
        }

        internal bool CanConnect()
        {
            if (!string.IsNullOrEmpty(this.SubscriptionId) &&
                this.MgmtCertificate != null)
            {
                return true;
            }
            return false;
        }
    }

    public abstract class DeployPageViewModelBase : ViewModelBase
    {
        protected VmRoleResourceExtensionViewModel ResExtViewModel;

        protected ResExtAzureDeploymentData DeployData;

        protected Dispatcher CurrentDispatcher;

        internal string PageTitle { get; set; }

        protected DeployPageViewModelBase(VmRoleResourceExtensionViewModel resExtViewModel,
            ResExtAzureDeploymentData deployWizardData)
        {
            this.ResExtViewModel = resExtViewModel;
            this.DeployData = deployWizardData;
            this.CurrentDispatcher = Application.Current.Dispatcher;
            
            // check whether the rexext has payload
            this.DeployData.HasPayload = AzureHelper.HasAppPayload(resExtViewModel.ResourceExtensionDefinition);
        }

        internal abstract bool IsUserInputComplete { get; }

        internal abstract bool PerformNextStep();

        internal abstract string GetSettings();

        internal abstract string GetPowerShellScript();
    }
}
